package cn.tianyigps.m7.command;

import cn.tianyigps.m7.beans.ReplyDTO;
import cn.tianyigps.m7.beans.Task;
import cn.tianyigps.m7.cache.ChannelCache;
import cn.tianyigps.m7.template.RestTemplate;
import cn.tianyigps.m7.utils.MessageCoding;
import cn.tianyigps.m7.utils.PropertiesUtil;
import cn.tianyigps.m7.utils.StringAnalysisUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.socket.ChannelOutputShutdownException;
import io.netty.util.internal.StringUtil;
import lombok.*;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.io.IOException;
import java.util.Map;
import java.util.Optional;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Created with IDEA
 *
 * @description: 指令
 * @author: cui.guibin
 * @create: 2019/4/10 15:49
 **/
@Getter
@Setter
@ToString
@AllArgsConstructor
@NoArgsConstructor
public class Command {
    private  static Logger log = LogManager.getLogger(Command.class);
    private String id;
    private String equipmentId;
    private String equipmentName;
    private String content;
    private String cmdType;

    public Command(String equipmentId, String content, String cmdType) {
        this.equipmentId = equipmentId;
        this.content = content;
        this.cmdType = cmdType;
    }

    public static void sendCommand(Command command) throws IOException {
        if (!checkCommand(command))
            return;
        ChannelCache channelCache = ChannelCache.getInstance();
        ChannelHandlerContext ctx = (ChannelHandlerContext) channelCache.get(command.getEquipmentId());
        if (!Optional.ofNullable(ctx).isPresent()){
            throw new ChannelOutputShutdownException("设备 :"+command.getEquipmentId()+"  不在线");
        }
        try {
            // 生成指令
            byte[] bytes = generateCMD(command.getCmdType(), command.getContent());
            if (bytes == null || bytes.length <= 0)
                return;
            ctx.writeAndFlush(Unpooled.copiedBuffer(bytes));
        } catch (Exception e) {
            throw new IOException("解析指令解析失败：" + command);
        }
        log.info("设备： " + command.getEquipmentId() + "  下发指令为：" + command.getContent());
    }
    private static byte[] generateCMD(String type,String cmd) {

        byte[] bytes;
        StringBuilder builder = new StringBuilder();
        builder.append("7878");
        switch (type){
            case "restart":
                builder.append("12800A00000001524553455423");
                break;
            case "platform":
                Matcher matcher = Pattern.compile("[^//]*?\\.(com|cn|net|org|biz|info|cc|tv)", Pattern.CASE_INSENSITIVE).matcher(cmd);
                boolean b = matcher.find();
                builder.append("Z180Z200000001");
                String pfString = null;
                if (b){
                    pfString = "SERVER,1," + cmd + ",0#";
                }else{
                    cmd = cmd.replace(":", ",");
                    pfString = "SERVER,0," + cmd + ",0#";
                }
                pfString = StringAnalysisUtil.convertToHexStr(pfString);
                builder.append(pfString);
                int pfPackageLength = 6 + pfString.length()/2 + 6;
                int pfCmdLength = 4 + pfString.length()/2;
                builder.replace(4,6,String.format("%02x",pfPackageLength).toUpperCase());
                builder.replace(8,10,String.format("%02x",pfCmdLength).toUpperCase());
                break;
            case "platformIp":
                builder.append("Z180Z200000001");
                cmd = cmd.replace(":", ",");
                String pfiString = "SERVER,0," + cmd + ",0#";
                pfiString = StringAnalysisUtil.convertToHexStr(pfiString);
                builder.append(pfiString);
                int pfiPackageLength = 6 + pfiString.length()/2 + 6;
                int pfiCmdLength = 4 + pfiString.length()/2;
                builder.replace(4,6,String.format("%02x",pfiPackageLength).toUpperCase());
                builder.replace(8,10,String.format("%02x",pfiCmdLength).toUpperCase());
                break;
            case "platformDomain":
                builder.append("Z180Z200000001");
                cmd = cmd.replace(":", ",");
                String pfdString = "SERVER,1," + cmd + ",0#";
                pfdString = StringAnalysisUtil.convertToHexStr(pfdString);
                builder.append(pfdString);
                int pfdPackageLength = 6 + pfdString.length()/2 + 6;
                int pfdCmdLength = 4 + pfdString.length()/2;
                builder.replace(4,6,String.format("%02x",pfdPackageLength).toUpperCase());
                builder.replace(8,10,String.format("%02x",pfdCmdLength).toUpperCase());

                break;
            case "disconnectOilEle":
                String cofString = StringAnalysisUtil.convertToHexStr("RELAY,1#");
                builder.append("14800C00000001" + cofString);
                break;
            case "restoreOilEle":
                String rofString = StringAnalysisUtil.convertToHexStr("RELAY,0#");
                builder.append("14800C00000001"+ rofString);
                break;
            default:

        }
        builder.append("0002005F0B4B0D0A");
        String string = builder.toString();
        bytes = MessageCoding.hexStringToBytes(string);
        return bytes;
    }
    private static boolean checkCommand(Command command) {
        if (!Optional.ofNullable(command).isPresent())
            return false;
        if (StringUtil.isNullOrEmpty(command.getCmdType()))
            return false;
        if (StringUtil.isNullOrEmpty(command.getEquipmentId()))
            return false;
        return true;
    }
    /**
     * @param: String type String cmd
     * @return
     * @author cui.guibin
     * @date 2019/4/15 16:11
     * 指令发送后的回调接口
     *
     */
    public static void instructionReply(String equipmentId,String message,int code) {
        ReplyDTO replyDTO = null;
        if (StringUtil.isNullOrEmpty(equipmentId)) {
            log.error("错误指令无设备号");
            replyDTO = new ReplyDTO(equipmentId,400, false, "错误指令无设备号");
        }
        switch (code){
            case 200:
                replyDTO = new ReplyDTO(equipmentId,code, true, message);
                break;
            case 406:
                replyDTO = new ReplyDTO(equipmentId,code, false, message);
                break;
                default:
        }
        String url = PropertiesUtil.getStr("order.callback.url", "constant.properties");
        boolean post= false;
        try {
            post = RestTemplate.post(url, replyDTO);
        } catch (IOException e) {
            log.error("接口调用失败： " + replyDTO.toString());
            e.printStackTrace();
        }
        if (!post){
            log.error("接口调用失败： " + url + "params： " + replyDTO.toString());
        }
    }
}
